package myapps.LetsPlayAGame;

import java.util.List;

import javax.ws.rs.core.NewCookie;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

/**
 * Simple REST client that plays a game of ROTA until the opponent loses or gives up the goodies...
 *
 * The board will be represented as a string, where each position corresponds to a position on the board. Board positioning is as follows:
 * 1 2 3
 * 4 5 6     each position has a number 1-9
 * 7 8 9
 * 
 * - represents an empty space
 * c represents a space occupied by a computer piece
 * p represents a space occupied by a player piece
 */
public class Rota 
{
	private static final String baseURL = "http://rota.praetorian.com/rota/service/play.php";

	private final Client client;
	private List<NewCookie> cookies;
	private final WebResource resource;

	public Rota() {
		client = Client.create();
		resource = client.resource(baseURL);
		cookies = null;
	}

	public static void main( String[] args )
	{
		Rota rota = new Rota();
		rota.beginTheSiege();
	}

	private void beginTheSiege() {
		boolean failure = true;

		GameState state = new GameState();
		System.out.println("Shall we play a game?");
		try {
			//Failure is not an option, try try again...
			while(failure){

				//If game is not running, start one up
				if(state.isGameRunning() == false){
					state.update(newGame());
					System.out.println(state.getState());
				}
				//else if one of the valid phases, determine optimal play
				else if(state.isPlacePhase() ^ state.isMovePhase()){
					state.update(determinePlay(state.getBoard()));
				}				
				//Invalid game state
				else{
					throw new RuntimeException("Failed : Invalid game state : \n" + state.getState());
				}
				
				if(state.getHash() != null){
					failure = false;
					System.out.println(state.getHash());
				}
				//Timeout seems to happen somewhere between 8 and 12 seconds, so anything below that should work.
				Thread.sleep(3000);
				
			}
			System.out.println("A strange game. The only winning move is not to play. How about a nice game of chess?");

		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Since it's fairly simple to create an infinite game with a small number of states, and the opponent is extremely predictable,
	 * this method only needs to know a few valid states.
	 * @param state
	 * @return
	 */
	private String determinePlay(String state) {
		switch (state) {
		case "---------":  return(placePiece(1));
		case "pc-------":  return(placePiece(5));
		case "pc--p---c":  return(placePiece(3));
		case "pcpcp---c":  return(movePiece(5,8));
		case "p-pcc--pc":  return(movePiece(3,6));
		case "pc-c-p-pc":  return(movePiece(6,3));
		default: return(newGame());
		}
	}

	/**
	 * Utility method to GET a WebResource.  If cookies for the session have not been created, then the cookies from the first response will be used for further session information.
	 * @param resource
	 * @return json response
	 */
	private String getResponse(WebResource resource) {
		ClientResponse response;
		if(cookies == null){
			response = resource.accept("application/json").get(ClientResponse.class);
			cookies = response.getCookies();
		}
		else{
			WebResource.Builder builder = resource.getRequestBuilder();
			builder = builder.accept("application/json");
			for (NewCookie cookie : cookies){
				builder = builder.cookie(cookie);
			}
			response = builder.accept("application/json").get(ClientResponse.class);
		}

		if (response.getStatus() != 200) {
			throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
		}

		String string = response.getEntity(String.class);
		System.out.println("Response : " + string);
		return string;
	}

	/**
	 * Starts a new game, returning the ClientResponse
	 * @return json response
	 */
	private String newGame() {
		System.out.println("Starting a new game");
		cookies = null;
		return getResponse(resource.queryParam("request", "new"));
	}
	
	/**
	 * Move a piece from i to j
	 * @param i
	 * @param j
	 * @return json response
	 */
	private String movePiece(int i, int j) {
		System.out.println("Moving piece " + i + " to " + j);
		return getResponse(resource.queryParam("request", "move").queryParam("from", String.valueOf(i)).queryParam("to", String.valueOf(j)));
	}

	/**
	 * Place a piece at i
	 * @param i
	 * @return json reponse
	 */
	private String placePiece(int i) {
		System.out.println("Placeing a piece in position " + i);
		return getResponse(resource.queryParam("request", "place").queryParam("location", String.valueOf(i)));
	}
}
